package cn.qdhlm.collectservice.core.component;


import cn.qdhlm.collectservice.common.Constant;
import cn.qdhlm.collectservice.common.util.CodeUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import lombok.extern.log4j.Log4j2;

/**
 * @Name: Checker
 * @Description: Checker
 * @Author: jiangcs
 */
@Log4j2
public class Checker {
    /**
     * 报文校验：
     * <p>
     * 1、格式为 68 ** ** 68
     * 2、长度是否匹配
     * 3、帧校验和是否正确
     * 4、结尾为 16
     * <p>
     * 注：此处使用ByteBuf.get(i)方法，避免可读指针移动
     *
     * @param byteBuf
     * @return
     */
    public static boolean check(ByteBuf byteBuf) {
        log.info("check begin ...");
        log.info("check byteBuf: {}", ByteBufUtil.hexDump(byteBuf));

        try {
            // 起止字符 68
            String symbolStart = CodeUtil.byteToHexString(byteBuf.getByte(0));
            String symbolEnd = CodeUtil.byteToHexString(byteBuf.getByte(5));
            if (!Constant.SYMBOL_68.equals(symbolStart) || !Constant.SYMBOL_68.equals(symbolEnd)) {
                throw new RuntimeException("symbol start[" + symbolStart + "] and end[" + symbolEnd + "] are not all " + Constant.SYMBOL_68);
            }
            // 数据长度
            int dataLength1 = byteBuf.getShortLE(1);
            int dataLength2 = byteBuf.getShortLE(3);
            if (dataLength1 != dataLength2) {
                throw new RuntimeException("dataLength1[" + dataLength1 + "] and dataLength2[" + dataLength2 + "] are not equal");
            }
            // 数据长度: 总长度-68-L-L-68-帧校验和-结束
            int actualDataLength = byteBuf.readableBytes() - 6 - 1 - 1;
            if (dataLength1 != actualDataLength) {
                throw new RuntimeException("dataLength1[" + dataLength1 + "] and actualDataLength[" + actualDataLength + "] are not equal");
            }
            // 控制域 80
            String controlCode = CodeUtil.byteToHexString(byteBuf.getByte(6));
            if (!Constant.SYMBOL_80.equals(controlCode)) {
                throw new RuntimeException("controlCode[" + controlCode + "] is not " + Constant.SYMBOL_80);
            }
            // 帧校验和
            int checksumIndex = byteBuf.readableBytes() - 2;
            int checksum = byteBuf.getUnsignedByte(checksumIndex);
            int actualSum = 0;
            for (int i = 6; i < checksumIndex; i++) {
                actualSum += byteBuf.getUnsignedByte(i);
            }
            int actualChecksum = actualSum % 256;
            if (checksum != actualChecksum) {
                throw new RuntimeException("checksumIndex[" + checksumIndex + "]: checksum[" + checksum + "] and actualChecksum[" + actualChecksum + "] are not equal");
            }
            // 结尾字符 16
            String symbolTail = CodeUtil.byteToHexString(byteBuf.getByte(7 + dataLength1));
            if (!Constant.SYMBOL_16.equals(symbolTail)) {
                throw new RuntimeException("symbol tail[" + symbolTail + "] is not " + Constant.SYMBOL_16);
            }

            log.info("check end ...");
            return true;
        } catch (Exception e) {
            log.error("check exception: {}", e.getMessage());
            return false;
        }
    }
}
